package cn.sccl.common.spring;

import cn.sccl.common.exception.BusinessException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 针对Rest处理异常信息。
 * 如果发生异常，将异常信息按json（或xml，根据配置决定）封装到response中，避免返回html信息
 * Created by dell on 2015/4/11.
 */
@ControllerAdvice(annotations = {RestController.class})
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

    private Log logger = LogFactory.getLog(RestResponseEntityExceptionHandler.class);

    /**
     * 将异常信息处理到response中
     * A single place to customize the response body of all Exception types.
     * This method returns {@code null} by default.
     *
     * @param ex      the exception
     * @param body    the body to use for the response
     * @param headers the headers to be written to the response
     * @param status  the selected response status
     * @param request the current request
     */
    @Override
    protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {
        ServletWebRequest webRequest = (ServletWebRequest) request;
        String url = "[" + webRequest.getRequest().getMethod() + "] | ";
        url += webRequest.getRequest().getRequestURL().toString();
        if (webRequest.getRequest().getQueryString() != null) {
            url += "?" + webRequest.getRequest().getQueryString();
        }
        logger.error("调用报错：" + url);
        ex.printStackTrace();

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("errorMsg", ex.getLocalizedMessage());
        map.put("errorClass", ex.getClass().getName());
        map.put("error", ex);
        if (ex instanceof BusinessException) {
            map.put("errorCode", ((BusinessException) ex).getErrorCode());
        }
        ResponseEntity<Object> re = super.handleExceptionInternal(ex, map, headers, status, request);//主要是此处传入了map，如果为空，会返回错误的html信息，不为空，则返回json
        return re;
    }


    /**
     * 处理RuntimeException异常
     * 如果还有未处理的异常类型，可以直接在@ExceptionHandler中增加
     *
     * @param ex
     * @param request
     * @return
     */
    @ExceptionHandler(value = {RuntimeException.class, IOException.class})
    public ResponseEntity<Object> handleRunTimeException(Exception ex, WebRequest request) {
        HttpHeaders headers = new HttpHeaders();
        HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
        ResponseStatus rs = ex.getClass().getAnnotation(ResponseStatus.class);
        if (rs != null) {
            status = rs.value();
        }
        return handleExceptionInternal(ex, null, headers, status, request);
    }
}
